package com.dh.blog.controllers.admin;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.dh.blog.handler.SaveFileHandler;
import com.dh.blog.service.ArticleService;
import com.dh.blog.service.BlogService;
import com.dh.blog.utils.PagerUtils;
import com.dh.blog.vo.ArticlePagerVo;
import com.dh.blog.vo.ArticleVo;
import com.ewei.web.common.exception.MessageRuntimeException;
import com.ewei.web.common.io.BufferedRandomAccessFile;
import com.ewei.web.common.json.resolver.JsonModel;
import com.ewei.web.common.json.resolver.JsonModelMap;
import com.ewei.web.common.response.ResponseVO;
import com.ewei.web.common.utils.FileToolsBar;
import com.ewei.web.common.validator.SaveGroup;
import com.ewei.web.common.validator.UpdateGroup;
import com.mysql.jdbc.StringUtils;
@RequestMapping("/admin/article")
@Controller
//@Authority TODO 文章权限
public class AdminArticleController {
	private final String identify = "694af96a64e711e6961d00ff8a62d83e";
	private static final Pattern pattern = Pattern.compile("/admin/article/md(/[\\S]+)");
	@Resource
	private Properties config;
	@Autowired
	private SaveFileHandler saveFile;
	@Resource(name="MySQLArticleService")
	private ArticleService articleService;
	@Resource
	private BlogService blogService;
	/**
	 * 查找文章
	 */
	@RequestMapping(value="/{article_id:\\w+}",method=RequestMethod.GET)
	@ResponseBody
	public Object find(@PathVariable("article_id")Integer articleId){
		ArticleVo article = articleService.getArticleById(articleId);
		String mdPath = article.getDiskpath();
		String diskDir = config.getProperty("file_disk_dir");
		String mdDir = config.getProperty("blog_md_dir");
		mdPath = (StringUtils.isNullOrEmpty(mdDir)?"":mdDir) + mdPath;
		mdPath = (StringUtils.isNullOrEmpty(diskDir)?"":diskDir) + mdPath;
		StringBuilder builder = new StringBuilder();//想来想去还是直接原生地读取md文件快（反正不大）
		try{
			BufferedRandomAccessFile file = new BufferedRandomAccessFile(new File(mdPath), "rw");
			String str = null;
			while(null != (str = file.readBufferLine())){
				builder.append(str);
			}
			file.close();
			article.setMd(builder.toString());
		}catch(Exception ex){
			throw new MessageRuntimeException(ex);
		}
		return new ResponseVO().setDatas(article);
	}
	/**
	 * 创建文章
	 * @param article
	 * @param result
	 * @return
	 */
	@RequestMapping(value="",method=RequestMethod.POST)
	@ResponseBody
	public Object add(@JsonModel @Validated({SaveGroup.class})ArticleVo article,
			BindingResult result){
		if(result.hasErrors()){
			return new ResponseVO().resolveError(result);
		}
		System.out.println("classify:"+article.getClassify().getId());
		article.setBlog(blogService.getBlogById(identify));
		String diskpath = saveFile.saveByDate(null,
			Calendar.getInstance().getTime());
		String mdPath = config.getProperty("blog_md_dir");
		mdPath = ((null!=mdPath)?mdPath:"")+diskpath;
		saveFile.saveByRelative(null, mdPath);
		article.setDiskpath(diskpath);
		articleService.doCreateArticle(article);
		System.out.println("id:"+article.getId());
		if(article.getMd() != null && article.getContent() != null){
			edit(article, result, article.getId());
		}
		return new ResponseVO().setDatas(article);
	}
	/**
	 * 编辑文章，保持幂等性
	 * @param article
	 * @param result
	 * @return
	 */
	@RequestMapping(value="/{article_id:\\w+}",method=RequestMethod.PUT)
	@ResponseBody
	public Object edit(@JsonModel @Validated({UpdateGroup.class})ArticleVo article,
			BindingResult result,@PathVariable("article_id")Integer articleId){
		if(result.hasErrors()){
			return new ResponseVO().resolveError(result);
		}
		ArticleVo oldOne = null;
		if(null == (oldOne = articleService.getArticleById(articleId))){//验证文章id的有效性
			return new ResponseVO().error("401",config.get("401"));
		}
		ArticleVo updateOne = new ArticleVo();//为了排除一些干扰属性,新建个更新对象(更新速度加快些许)
		updateOne.setUpdateTime(Calendar.getInstance().getTimeInMillis());//设置更新的时间
		updateOne.setId(articleId);
		updateOne.setTitle(article.getTitle().trim());
		updateOne.setDescription(article.getDescription().trim());
		updateOne.setVisiable(oldOne.getVisiable());
		updateOne.setIrelease(oldOne.getIrelease());
		updateOne.setIcommand(oldOne.getIcommand());
		if(articleService.doUpdateArticle(updateOne,oldOne.getUpdateTime()) <=0 ){//更新
			return new ResponseVO().error("403",config.get("403"));//更新失败
		}
		String content = article.getContent();
		String md = article.getMd();
		String diskpath = oldOne.getDiskpath();
		content = content.replace("<br/>", "\n");//html存储的时候要去掉<br/>
		if(null != content && !"".equals(content.trim())){//将具体内容存在文件里
			try{
				ByteArrayInputStream in = 
						new ByteArrayInputStream(content.getBytes("UTF-8"));//编码成字节流
				saveFile.saveByRelative(in, diskpath);//转储文件
			}catch(IOException ex){
				throw new MessageRuntimeException(ex);
			}
		}
		if(null != md && !"".equals(md.trim())){//将文章的md存储在文件中
			try{
				String mdPath = config.getProperty("blog_md_dir");
				mdPath = ((null!=mdPath)?mdPath:"")+diskpath;
				ByteArrayInputStream in = 
						new ByteArrayInputStream(md.getBytes("UTF-8"));//编码成字节流
				saveFile.saveByRelative(in, mdPath);
			}catch(IOException ex){
				throw new MessageRuntimeException(ex);
			}
		}
		return new ResponseVO();
	}
	/**
	 * 修改文章状态
	 * @return
	 */
	@RequestMapping(value="/status/{article_id:\\w+}",method=RequestMethod.PUT)
	@ResponseBody
	public Object status(@JsonModel ArticleVo articleVo,@PathVariable("article_id")Integer articleId){
		ArticleVo updateOne = new ArticleVo();
		updateOne.setVisiable(articleVo.getVisiable());
		updateOne.setIrelease(articleVo.getIrelease());
		updateOne.setIcommand(articleVo.getIcommand());
		articleVo = articleService.getArticleById(articleId);
		if(updateOne.getIrelease() > articleVo.getIrelease()){//对发表文章的状态改变要触发发布文章的业务逻辑
			return publish(articleId);
		}else if(updateOne.getIrelease() < articleVo.getIrelease()){
			return cpublish(articleId);
		}
		updateOne.setId(articleId);
		articleService.doUpdateArticle(updateOne,articleVo.getUpdateTime());
		return new ResponseVO();
	}
	/**
	 * 文章发表
	 * @param articleId
	 * @return
	 */
	@RequestMapping(value="/pub/{article_id:\\w+}",method=RequestMethod.PUT)
	@ResponseBody
	public Object publish(@PathVariable("article_id")Integer articleId){
		ArticleVo article = null;
		if(null == (article = articleService.getArticleById(articleId))){//先查找文章出来
			return new ResponseVO().error("401",config.get("401"));
		}
		article.setId(articleId);
		article.setVisiable(1);//设置为可见
		article.setIrelease(1);//改变发表标识符
		article.setReleaseTime(Calendar.getInstance().getTime());
		if(!articleService.doPublish(article)){
			return new ResponseVO().error("404",config.get("404"));//发布文章失败
		};
		return new ResponseVO();
	}
	/**
	 * 文章下架（取消发表）
	 * @param articleId
	 * @return
	 */
	@RequestMapping(value="/cpub/{article_id:\\w+}",method=RequestMethod.PUT)
	public Object cpublish(@PathVariable("article_id")Integer articleId){
		ArticleVo article = null;
		if(null == (article = articleService.getArticleById(articleId))){
			return new ResponseVO().error("401",config.get("401"));
		}
		article.setId(articleId);
		article.setVisiable(0);
		article.setIrelease(0);
		articleService.doCancelPublish(article);
		return new ResponseVO();
	}
	@RequestMapping(value="/pager",method=RequestMethod.GET)
	@ResponseBody
	public Object pager(@JsonModel ArticlePagerVo pager){
		//identify就是博客ID了
		int num = pager.getNum();
		int size = pager.getSize();
		int total = articleService.countByBlog(identify);//admin的文章先不做分类
		int pages = total/pager.getSize();
		if(pager.getSize()*pages<total){
			pages++;
		}
		if(num>pages){
			throw new IndexOutOfBoundsException();
		}
		pager.setBlogId(identify);
		pager.setOffset((num-1)*pager.getSize());
		pager = (ArticlePagerVo) articleService.getPagerByBlogAndQueryAdmin(pager);
		pager.setNum(num);
		pager.setTotal(total);
		pager.setPages(pages);
		pager.setSize(size);
		PagerUtils.rangeMake(pager);
		return new ResponseVO().setDatas(pager);
	}
	/**
	 * 文章编辑器页面
	 * @param articleId
	 * @return
	 */
	@RequestMapping(value="/editor/{article_id:\\w+}",method=RequestMethod.GET)
	@ResponseBody
	public ModelAndView editor(@PathVariable("article_id")Integer articleId){
		ModelAndView view = new ModelAndView("admin/editor");
		if(articleService.existsArticle(articleId)<=0){
			throw new MessageRuntimeException("the article doesn't exist");
		}
		view.addObject("id", articleId);
		return view;
	}
	@RequestMapping(value="/editor",method=RequestMethod.GET)
	@ResponseBody
	public ModelAndView editor0(@JsonModel JsonModelMap map){
		Integer classifyId = map.getInteger("classifyId");
		if(null == classifyId){
			throw new MessageRuntimeException("illegal request");
		}
		ModelAndView view = new ModelAndView("admin/editor");
		view.addObject("classifyId",classifyId);
		return view;
	}
}
